package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.common.constants.ApCommentConstants;
import com.heima.common.exception.CustomException;
import com.heima.feign.article.IArticleClient;
import com.heima.feign.user.IUserClient;
import com.heima.model.article.dtos.ArticleCommentConfigDto;
import com.heima.model.article.dtos.ArticleCommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentManageDto;
import com.heima.model.comment.dtos.CommentRepaySaveDto;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.thread.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.pojos.*;
import com.heima.wemedia.service.WmCommentManageService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.Date;
import java.util.stream.Collectors;


/**
 * @author jgs
 * @create 2023-06-28 16:57
 */
@Service
public class WmCommentManageServiceImpl implements WmCommentManageService {
    @Autowired
    private IArticleClient iArticleClient;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private KafkaTemplate kafkaTemplate;
    @Autowired
    private WmUserMapper wmUserMapper;
    @Autowired
    private IUserClient iUserClient;

    /**
     * 评论列表查询
     *
     * @param dto
     * @return
     */
    /**
     * 查询评论详情
     *
     * @param dto
     * @return
     */
    @Override
    public PageResponseResult findAllComments(ArticleCommentDto dto) {
        //参数校验
        if (dto == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmUser apUser = WmThreadLocalUtil.getUser();
        //判断用户是否登录
        if (apUser == null) {
//            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        dto.setWmUserId(apUser.getId());
        return iArticleClient.findNewsComments(dto);
    }

    /**
     * 删除评论
     *
     * @param commentId
     * @return
     */
    @Override
    @Transactional
    public ResponseResult deleteComment(String commentId) {
        //查询mongoDB评论是否存在
        ApComment apComment = mongoTemplate.findOne(Query.query(Criteria.where("id").is(commentId)), ApComment.class);
        if (apComment == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //设计查询条件
        Query query = Query.query(Criteria.where("commentId").is(commentId));
        List<ApCommentRepay> apCommentRepayList = mongoTemplate.find(query, ApCommentRepay.class);
        //获取回复表评论条数
        Integer commentSize = apCommentRepayList.size();
        //存在回复评论进行删除
        if (commentSize > 0) {
            //删除评论回复表数据
            //删除评论回复点赞表
            for (ApCommentRepay apCommentRepay : apCommentRepayList) {
                mongoTemplate.remove(Query.query(Criteria.where("id").is(apCommentRepay.getId())), ApCommentRepay.class);
                mongoTemplate.remove(Query.query(Criteria.where("commentRepayId").is(apCommentRepay.getId())), ApCommentRepayLike.class);
            }
        }
        //删除评论点赞表
        mongoTemplate.remove(query, ApCommentLike.class);
        //删除评论表
        mongoTemplate.remove(apComment);

        //给kafka发消息,更新评论数量
        Map map = new HashMap();
        map.put("articleId", apComment.getEntryId());
        map.put("add", -(commentSize + 1));
        kafkaTemplate.send(ApCommentConstants.AP_COMMENT_SYNC_ARTICLE, JSON.toJSONString(map));

        //查询数据库
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);

    }

    /**
     * 删除评论回复
     *
     * @param commentRepayId
     * @return
     */
    @Override
    public ResponseResult deleteCommentRepay(String commentRepayId) {
        //1.校验参数
        ApCommentRepay apCommentRepay = mongoTemplate.findById(commentRepayId, ApCommentRepay.class);
        if (apCommentRepay == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //2.删除评论回复及点赞
        mongoTemplate.remove(Query.query(Criteria.where("id").is(apCommentRepay.getId())),ApCommentRepay.class);
        mongoTemplate.remove(Query.query(Criteria.where("commentRepayId").is(apCommentRepay.getId())), ApCommentRepayLike.class);
        //3.更新评论回复数量
        ApComment apComment = mongoTemplate.findById(apCommentRepay.getCommentId(), ApComment.class);
        apComment.setReply(apComment.getReply() - 1);
        mongoTemplate.save(apComment);

        //4.向kafka发送消息,修改评论数量
        Map map = new HashMap();
        map.put("articleId", apComment.getEntryId());
        map.put("add", -1);
        kafkaTemplate.send(ApCommentConstants.AP_COMMENT_SYNC_ARTICLE, JSON.toJSONString(map));

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * description: 回复评论
     *
     * @Param [dto]
     * com.heima.model.common.dtos.ResponseResult
     */
    public ResponseResult repayComment(CommentRepaySaveDto dto) {
        //1 参数校验
        if (dto == null || StringUtils.isEmpty(dto.getContent()) || dto.getCommentId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        if (dto.getContent().length() > 200) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "评论字数过多，请勿超过200字");
        }
        //2 根据拦截的userId查询数据库中的自媒体作者人id wmUser
        WmUser wmUser = wmUserMapper.selectById(WmThreadLocalUtil.getUser().getId());
        if (wmUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        ApCommentRepay apCommentRepay = new ApCommentRepay();

        apCommentRepay.setAuthorId(wmUser.getId());
        apCommentRepay.setAuthorName(wmUser.getName());
        apCommentRepay.setCommentId(dto.getCommentId());
        apCommentRepay.setContent(dto.getContent());
        apCommentRepay.setLikes(0);
        apCommentRepay.setCreatedTime(new Date());
        apCommentRepay.setUpdatedTime(new Date());
        // 保存
        mongoTemplate.save(apCommentRepay,"ap_comment_repay");

        //3. 更新ApComment表回复表数量
       // 根据id查询commentId
        ApComment apComment = mongoTemplate.findById(apCommentRepay.getCommentId(), ApComment.class);
        if (apComment.getReply() == null)
            apComment.setReply(0);

        apComment.setReply(apComment.getReply() + 1);
        mongoTemplate.save(apComment,"ap_comment");

        //4. 向kafka发送消息，修改评论数量
        Map map =new HashMap();
        map.put("articleId",apComment.getEntryId());
        map.put("add",1);
        kafkaTemplate.send(ApCommentConstants.AP_COMMENT_SYNC_ARTICLE,JSON.toJSONString(map));

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * description: 查看评论列表
     *
     * @Param [dto]
     * com.heima.model.common.dtos.ResponseResult
     */
    @Override
    public ResponseResult listComment(CommentManageDto dto) {
        //1 创建队列
        List<CommentRepayListVo> commentRepayListVoList = new ArrayList<>();
        //2 根据文章id查询评论id
        Query query = Query.query(Criteria.where("entryId").is(dto.getArticleId()));
        //3 根据创建时间倒叙排序查到的评论
        Pageable pageable = PageRequest.of(dto.getPage() - 1, dto.getSize());
        query.with(pageable);
        query.with(Sort.by(Sort.Direction.DESC, "createdTime"));

        //4 查询数据库mongoDB评论
        List<ApComment> commentLists = mongoTemplate.find(query, ApComment.class);
        for (ApComment apComment : commentLists) {
            //遍历加入vo队列
            CommentRepayListVo vo = new CommentRepayListVo();
            vo.setApComments(apComment);
            Query query1 = Query.query(Criteria.where("commentId").is(apComment.getId()));
            query1.with(Sort.by(Sort.Direction.DESC, "createdTime"));
            List<ApCommentRepay> apCommentRepays = mongoTemplate.find(query1, ApCommentRepay.class);
            vo.setApCommentRepays(apCommentRepays);

            //5 vo对象添加到list集合中
            commentRepayListVoList.add(vo);
        }
        return ResponseResult.okResult(commentRepayListVoList);
    }

    /**
     * 打开或关闭评论
     * @param dto
     * @return
     */
    @Override
    public ResponseResult setCommentStasus(ArticleCommentConfigDto dto) {
        //参数校验
        if(dto==null||dto.getOperation()>1||dto.getOperation()<0){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmUser wmUser = WmThreadLocalUtil.getUser();
        //判断用户是否登录
        if (wmUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //app端用户id
        WmUser dbUser = wmUserMapper.selectById(wmUser.getId());
        Integer apUserId = dbUser.getApUserId();

        //清空该文章的所有评论
        List<ApComment> apCommentList = mongoTemplate.find(Query.query(Criteria.where("entryId").is(dto.getArticleId())),ApComment.class);
        for (ApComment apComment : apCommentList) {
            List<ApCommentRepay> commentRepayList = mongoTemplate.find(Query.query(Criteria.where("commentId").is(apComment.getId())), ApCommentRepay.class);
            List<String> commentRepayIdList = commentRepayList.stream().map(ApCommentRepay::getId).distinct().collect(Collectors.toList());
            //删除所有的评论回复点赞数据
            mongoTemplate.remove(Query.query(Criteria.where("commentRepayId").in(commentRepayIdList)), ApCommentRepayLike.class);
//删除该评论的所有的回复内容
            mongoTemplate.remove(Query.query(Criteria.where("id").in(commentRepayIdList)), ApCommentRepay.class);
//删除评论的点赞
            mongoTemplate.remove(Query.query(Criteria.where("commentId").is(apComment.getId())), ApCommentLike.class);
        }
        //删除评论
        mongoTemplate.remove(Query.query(Criteria.where("entryId").is(dto.getArticleId())),ApComment.class);

        //修改app文章的config配置
        return iArticleClient.updateCommentStatus(dto);
    }

    /**
     * 作者点赞评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult likeComment(CommentLikeDto dto) {
        //判断是否为作者
        WmUser wmUser = WmThreadLocalUtil.getUser();
        //获取文章id
        ApComment apComment =
                mongoTemplate.findOne(Query.query(Criteria.where("id").is(dto.getCommentId().toString())), ApComment.class);
//
//        if (!wmUser.getName().equals(apComment.getAuthorName())) {
//            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_ADMIND);
//        }

        //2.根据operation 对应的更新MongoDB中对应的数据     0：点赞       1：取消点赞
        if (dto.getOperation() == 0) {
            //点赞 插入一条数据到ap_comment_like ,同时更新ap_comment中 该条评论对应的likes点赞数+1
            ApCommentLike apCommentLike = new ApCommentLike();
            apCommentLike.setAuthorId(wmUser.getId());
            apCommentLike.setCommentId(dto.getCommentId());

            mongoTemplate.save(apCommentLike, "ap_comment_like");

            apComment.setLikes(apComment.getLikes() + 1);//评论点赞数+1


        } else {
            //取消点赞,删除MongoDB中该条数据 ,同时更新ap_comment中 该条评论对应的likes点赞数-1
            mongoTemplate.remove(Query.query(Criteria.where("authorId").is(wmUser.getId())
                    .and("commentId").is(dto.getCommentId())), "ap_comment_like");

            //更新该评论的点赞数
            apComment.setLikes(apComment.getLikes() - 1);
        }

        mongoTemplate.save(apComment); //更新评论详情

        //3.响应数据: 当前评论的点赞数
        Map resMap = new HashMap();
        resMap.put("likes", apComment.getLikes());
        return ResponseResult.okResult(resMap);
    }
}
